﻿using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Sgr.AspNetCore;
using Sgr.AspNetCore.Middlewares.RequestRoute;
using Sgr.AspNetCore.Middlewares.Security;
using System;
using System.Linq;

namespace Microsoft.AspNetCore.Builder
{
    public static class WebApplicationBuilderExtensions
    {
        private static readonly string[] ExcludedMimeTypes = { "image/jpeg", "image/png", "image/gif" };

        /// <summary>
        /// 添加安全头部服务
        /// </summary>
        /// <param name="builder">应用程序构建器</param>
        /// <returns>应用程序构建器</returns>
        public static WebApplicationBuilder AddSecurityHeaders(this WebApplicationBuilder builder)
        {
            // 从配置中读取选项
            builder.Services.Configure<SecurityHeadersOptions>(
                builder.Configuration.GetSection("Sgr:SecurityHeaders"));

            return builder;
        }

        /// <summary>
        /// 使用请求路由中间件
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseRequestRoute(this IApplicationBuilder app)
        {
            app.UseMiddleware<RequestRouteMiddleware>();
            return app;
        }

        /// <summary>
        /// 使用安全头部中间件
        /// </summary>
        /// <param name="app">应用程序构建器</param>
        /// <returns>应用程序构建器</returns>
        public static IApplicationBuilder UseSecurityHeaders(this IApplicationBuilder app)
        {
            app.UseMiddleware<SecurityHeadersMiddleware>();
            return app;
        }

        /// <summary>
        /// 配置响应压缩
        /// </summary>
        /// <remarks>
        ///
        /// 用途：
        ///     1. 启用响应压缩可以减少传输的数据量，提高页面加载速度。
        ///     2. 可以通过配置压缩级别和MIME类型来优化性能。
        ///     3. 可以根据需要排除某些MIME类型的压缩，例如图片类型。
        ///     4. 可以根据需要启用HTTPS压缩。
        ///     5. 可以根据需要配置最小压缩大小。
        ///
        /// 配置项说明：
        ///     EnableCompression     - 是否启用压缩
        ///     EnableForHttps       - 是否为HTTPS请求启用压缩
        ///     CompressionLevel     - 压缩级别 (Fastest/Optimal/NoCompression)
        ///     MinimumSizeToCompress - 最小压缩大小（字节）
        ///     MimeTypes           - 要压缩的MIME类型列表
        ///
        /// 压缩提供程序：
        ///     - Brotli：更高的压缩率，但需要更多CPU资源
        ///     - Gzip：较好的压缩率和CPU资源平衡
        ///
        /// 最佳实践：
        ///     1. 建议对文本类型启用压缩（JSON、XML、HTML等）
        ///     2. 图片、视频等已压缩的内容不建议启用压缩
        ///     3. 小于1KB的响应不建议压缩
        ///     4. 生产环境建议使用"Fastest"压缩级别
        ///     5. 开发环境可以禁用压缩以方便调试
        ///
        /// 中间件配置说明：
        ///     1. UseResponseCompression 中间件必须在其他中间件之前注册
        ///     2. 建议的中间件顺序：
        ///         - UseResponseCompression()    // 响应压缩
        ///         - UseHttpsRedirection()       // HTTPS重定向
        ///         - UseStaticFiles()           // 静态文件
        ///         - UseCors()                  // 跨域
        ///         - UseAuthentication()        // 身份认证
        ///         - UseAuthorization()         // 授权
        ///
        ///         // ... 其他中间件配置
        ///
        /// 配置文件示例：
        /// <code>
        /// {
        ///   "Compression": {
        ///     "EnableCompression": true,
        ///     "EnableForHttps": true,
        ///     "CompressionLevel": "Fastest",
        ///     "MinimumSizeToCompress": 1024,
        ///     "MimeTypes": [
        ///       "text/plain",
        ///       "text/html",
        ///       "text/css",
        ///       "text/xml",
        ///       "text/json",
        ///       "application/javascript",
        ///       "application/json",
        ///       "application/xml"
        ///     ]
        ///   }
        /// }
        /// </code>
        /// </remarks>
        /// <param name="builder">Web应用程序构建器</param>
        /// <returns>配置后的Web应用程序构建器</returns>
        public static WebApplicationBuilder ConfigureCompression(this WebApplicationBuilder builder)
        {
            //private static void ConfigureMiddleware(WebApplication app)
            //{
            //    var settings = app.Configuration
            //        .GetSection("Compression")
            //        .Get<CompressionSettings>();

            //    if (settings?.EnableCompression ?? false)
            //    {
            //        // 使用响应压缩（要在其他中间件之前）
            //        app.UseResponseCompression();
            //    }

            //    // ... 其他中间件配置
            //}

            var compressionSettings = builder.Configuration
                    .GetSection("Compression")
                    .Get<CompressionSettings>();

            if (!compressionSettings?.EnableCompression ?? false)
                return builder;

            builder.Services.AddResponseCompression(options =>
            {
                // 启用HTTPS压缩
                options.EnableForHttps = compressionSettings!.EnableForHttps;

                // 添加压缩提供程序
                options.Providers.Add<BrotliCompressionProvider>();
                options.Providers.Add<GzipCompressionProvider>();

                // 配置MIME类型
                options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                    compressionSettings!.MimeTypes ?? Array.Empty<string>());

                // 配置是否应压缩响应
                options.ExcludedMimeTypes = ExcludedMimeTypes;
            });

            // 配置Brotli压缩
            builder.Services.Configure<BrotliCompressionProviderOptions>(options =>
            {
                options.Level = compressionSettings!.CompressionLevel;
            });

            // 配置Gzip压缩
            builder.Services.Configure<GzipCompressionProviderOptions>(options =>
            {
                options.Level = compressionSettings!.CompressionLevel;
            });

            return builder;
        }

        /// <summary>
        /// 配置跨域策略
        /// </summary>
        /// <remarks>
        ///
        /// 用途：
        ///     1. 在开发环境中启用CORS以方便前端开发调试
        ///     2. 在生产环境中严格控制跨域访问，提高安全性
        ///     3. 可配置允许的源、方法和头部信息
        ///     4. 可配置是否允许携带凭据
        ///     5. 支持环境特定的跨域策略
        ///
        /// 配置项说明：
        ///     EnableCors        - 是否启用跨域
        ///     AllowedOrigins    - 允许的源（域名）列表
        ///     AllowedMethods    - 允许的HTTP方法列表
        ///     AllowedHeaders    - 允许的请求头列表
        ///     AllowCredentials  - 是否允许携带凭据
        ///
        /// 最佳实践：
        ///     1. 开发环境：启用较宽松的跨域策略便于调试
        ///     2. 生产环境：严格限制允许的来源
        ///     3. 只允许必要的HTTP方法和请求头
        ///     4. 谨慎配置AllowCredentials
        ///     5. 定期审查跨域策略
        ///
        /// 中间件配置说明：
        ///     1. UseCors中间件应在UseRouting之后，UseEndpoints之前
        ///     2. 建议的中间件顺序：
        ///         - UseHttpsRedirection()
        ///         - UseStaticFiles()
        ///         - UseCors()           // 跨域中间件
        ///         - UseAuthentication()
        ///         - UseAuthorization()
        ///
        /// 配置文件示例：
        /// <code>
        /// {
        ///   "Cors": {
        ///     "EnableCors": true,
        ///     "AllowedOrigins": [
        ///       "http://localhost:3000",
        ///       "http://localhost:8080"
        ///     ],
        ///     "AllowedMethods": [
        ///       "GET",
        ///       "POST",
        ///       "PUT",
        ///       "DELETE",
        ///       "OPTIONS"
        ///     ],
        ///     "AllowedHeaders": [
        ///       "Content-Type",
        ///       "Authorization",
        ///       "X-Requested-With"
        ///     ],
        ///     "AllowCredentials": true
        ///   }
        /// }
        /// </code>
        /// </remarks>
        /// <param name="builder">Web应用程序构建器</param>
        /// <returns>配置后的Web应用程序构建器</returns>
        public static WebApplicationBuilder ConfigureCors(this WebApplicationBuilder builder)
        {
            //     3. 示例代码：
            //         var app = builder.Build();
            //
            //         var corsConfig = app.Configuration
            //             .GetSection("Cors")
            //             .Get<CorsSettings>();
            //
            //         if (corsConfig?.EnableCors ?? false)
            //         {
            //             app.UseCors("DefaultCorsPolicy");
            //         }

            var corsConfig = builder.Configuration
                .GetSection("Cors")
                .Get<CorsSettings>();

            if (!corsConfig?.EnableCors ?? false)
                return builder;

            // 添加跨域服务
            builder.Services.AddCors(options =>
            {
                // 添加默认的跨域策略
                options.AddPolicy("DefaultCorsPolicy", policy =>
                {
                    // 设置允许跨域的源、方法和头部信息
                    var corsBuilder = policy.WithOrigins(corsConfig!.AllowedOrigins.ToArray())
                                          .WithMethods(corsConfig!.AllowedMethods.ToArray())
                                          .WithHeaders(corsConfig!.AllowedHeaders.ToArray());

                    // 设置是否允许跨域请求携带凭据（如Cookie、HTTP认证等）
                    if (corsConfig!.AllowCredentials)
                        corsBuilder.AllowCredentials();
                    else
                        corsBuilder.DisallowCredentials();
                });
            });

            return builder;
        }
    }
}